using System;
using System.Collections.Generic;
using Xunit;
using WenYu.Core.Lexer;
using WenYu.Core.Parser;

namespace WenYu.Tests.DocumentValidation;

/// <summary>
/// 文档07-数组.md的示例验证测试
/// </summary>
public class Doc07ArraysValidation
{
    private List<Token> Tokenize(string source)
    {
        var lexer = new WenYuLexer(source);
        return lexer.Tokenize();
    }

    private Program Parse(string source)
    {
        var lexer = new WenYuLexer(source);
        var tokens = lexer.Tokenize();
        var parser = new WenYuParser(tokens);
        return parser.Parse();
    }

    #region 数组声明和初始化测试

    [Fact]
    public void Example1_ArrayDeclaration()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。
实型组 温度 是 【36.5, 37.2, 36.8】。
文字组 名单 是 【""小明"", ""小红"", ""小刚""】。
真假组 标记 是 【真真, 假假, 真真】。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("组", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example2_ArrayDeclareAndInit()
    {
        var source = @"整型组 分数。
分数 是 【85, 92, 78】。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 数组访问测试

    [Fact]
    public void Example3_AccessArrayElements()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。

整型 第一个分数 是 分数【0】。
整型 第二个分数 是 分数【1】。
整型 第三个分数 是 分数【2】。

输出（""第一个分数："" + 第一个分数的文字）。
输出（""第二个分数："" + 第二个分数的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example4_ModifyArrayElement()
    {
        var source = @"整型组 分数 是 【85, 92, 78】。
输出（分数【1】的文字）。

分数【1】 是 100。
输出（分数【1】的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 数组属性测试

    [Fact]
    public void Example5_ArrayProperties()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。

整型 数量 是 分数的长。
整型 第一个 是 分数的首。
整型 最后一个 是 分数的末。

输出（""数组长度："" + 数量的文字）。
输出（""第一个元素："" + 第一个的文字）。
输出（""最后一个元素："" + 最后一个的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 数组遍历测试

    [Fact]
    public void Example6_IterateWithIndex()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。

复 序 从 0 至 分数的长 - 1 步 1 {
    输出（""索引"" + 序的文字 + ""："" + 分数【序】的文字 + ""分""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example7_IterateElements()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。

复 分数 取 当前分数 {
    输出（""分数："" + 当前分数的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 数组方法测试

    [Fact]
    public void Example8_ArrayMethods()
    {
        var source = @"整型组 分数 是 【85, 92, 78】。
输出（""长度："" + 分数的长的文字）。

分数·添（88）。
输出（""长度："" + 分数的长的文字）。
输出（""最后一个："" + 分数的末的文字）。

分数·删（2）。
输出（""长度："" + 分数的长的文字）。

真假 有92分 是 分数·含（92）。
若 有92分 则{
    输出（""有人考了92分！""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 多维数组测试

    [Fact]
    public void Example9_TwoDimensionalArray()
    {
        var source = @"二维整型组 矩阵 是 【【1, 2, 3】, 【4, 5, 6】, 【7, 8, 9】】。

整型 元素 是 矩阵【1】【2】。
输出（元素的文字）。

矩阵【0】【0】 是 100。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("二维", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example10_Iterate2DArray()
    {
        var source = @"二维整型组 矩阵 是 【【1, 2, 3】, 【4, 5, 6】, 【7, 8, 9】】。

输出（""===矩阵===""）。
复 行 从 0 至 矩阵的长 - 1 步 1 {
    复 列 从 0 至 矩阵【行】的长 - 1 步 1 {
        整型 值 是 矩阵【行】【列】。
        输出（值的文字）。
    }
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 完整示例测试

    [Fact]
    public void Example11_CompleteArrayExample()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 88, 95】。

输出（""===成绩统计===""）。
输出（""总数："" + 分数的长的文字）。

整型 总分 是 0。
复 分数 取 分 {
    总分 是 总分 + 分。
}

输出（""总分："" + 总分的文字）。
输出（""平均分："" + (总分 ÷ 分数的长)的文字）。

输出（""===各科成绩===""）。
复 序 从 0 至 分数的长 - 1 步 1 {
    输出（""第"" + (序 + 1)的文字 + ""次考试："" + 分数【序】的文字 + ""分""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion
}
